package com.zhangmeng.tools.controller;

import com.zhangmeng.tools.utils.AlertUtils;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.util.Callback;
import javafx.util.StringConverter;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;


import java.net.URI;


/**
 * @author : 芊芊墨客
 * @version : 1.0
 * @date : 2023-02-25 15:04
 */
@Slf4j
public class NettyClientController {

    @FXML
    private Button send;

    @FXML
    private TextField url_address;

    @FXML
    private TextField port;

    @FXML
    private TextArea result_show;

    @FXML
    private Button connect;

    @FXML
    private TextArea send_msg;

    private WebSocketClient webSocketClient;

    /**
     * 本客户端后台是否已启动
     *
     * @since 2021-12-1
     */
    private boolean isStarted;

    private final ObservableList<Data> list = FXCollections.observableArrayList();
    private static ObservableList<String> message_result_list = FXCollections.observableArrayList();

    public static void clear_message(){
        NettyClientController.message_result_list.clear();
    }

    public static void add_message(String msg){
        NettyClientController.message_result_list.add(msg);
        NettyClientController.message_result_list.add(System.lineSeparator());
    }

    private static final int socket_port = 3333;
    private static final String socket_address = "127.0.0.1";

    static class Data{
        private String key;
        private Object value;

        public Data(String key, Object value) {
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public Object getValue() {
            return value;
        }

        public void setValue(Object value) {
            this.value = value;
        }
    }


    @FXML
    public void initialize() {
        message_result_list.addListener((ListChangeListener<String>) c -> {

            while (c.next()) {
                if (c.wasAdded()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (String s : message_result_list) {
                        stringBuilder.append(s);
                    }
                    receive(stringBuilder.toString());
                }
            }
        });

        if (port.getText().length() == 0) {
            port.setText(String.valueOf(socket_port));
        }

        if (url_address.getText().length() == 0) {
            url_address.setText(socket_address);
        }

        connect.setOnAction(event -> {
            getConnection();
        });

        send.setOnAction(event -> {

            if (send_msg.getText().length() == 0){
                AlertUtils.alert_warning("请输入内容再试!");
            }
            String msg = send_msg.getText();

            if (webSocketClient == null){
                AlertUtils.alert_warning("请先连接websocket服务器再试!");
                return;
            }

            webSocketClient.send(msg);
            add_message(msg);

            this.send_msg.requestFocus();
            this.send_msg.clear(); // TODO
        });
    }

    private void getConnection(){
        if (webSocketClient == null) {
            webSocketClient(Type.ws, url_address.getText(), Integer.parseInt(port.getText()), "/websocket", "userId=1&source=pc");
        }
    }

    public enum Type{
        ws("ws"),
        wss("wss")
        ;

        Type(String name) {
            this.name = name;
        }

        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public void webSocketClient(Type type,String socket_address,int socket_port,String path ,String params) {
        try {
             webSocketClient = new WebSocketClient(new URI(type.name + "://" + socket_address + ":" + socket_port + path + "?" + params), new Draft_6455()) {
                //连接服务端时触发
                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    log.info("websocket客户端和服务器连接成功");
                    add_message("websocket客户端和服务器连接成功!");
                }
                //收到服务端消息时触发
                @Override
                public void onMessage(String message) {
                    log.info("websocket客户端收到消息={}", message);
                    add_message("websocket客户端收到消息={" + message + "}");
                }
                //和服务端断开连接时触发
                @Override
                public void onClose(int code, String reason, boolean remote) {
                    log.info("websocket客户端退出连接");
                    add_message("websocket客户端退出连接");
                }
                //连接异常时触发
                @Override
                public void onError(Exception ex) {
                    log.info("websocket客户端和服务器连接发生错误={}", ex.getMessage());
                    add_message("websocket客户端和服务器连接发生错误={" + ex.getMessage() + "}");
                }
            };
            webSocketClient.connect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public  void receive(String msg) {
        Platform.runLater(() -> {
            this.result_show.setText(msg);
        });

    }
}
